#!/bin/bash
# =================================================================
# GitLab Docker 一键恢复脚本（配合 auto_backup_gitlab.sh 使用）
# 支持：./restore_gitlab.sh            # 恢复最新备份
#      ./restore_gitlab.sh 2025-10-24 # 恢复指定日期备份
# =================================================================

set -euo pipefail

# ------------------------------
# 基本配置
# ------------------------------
CONTAINER_NAME="gitlab"           # GitLab 容器名称
BACKUP_BASE="./all_backup"        # 本地备份根目录
CONFIG_DIR="./config"             # GitLab 配置挂载目录
LOG_DIR="./logs"                  # GitLab 日志挂载目录
DATA_DIR="./data"                 # GitLab 数据挂载目录

# ------------------------------
# 传参与默认逻辑
# ------------------------------
# 若脚本第一个参数存在，则使用该日期；否则自动选择最新备份目录
if [ "${1:-}" != "" ]; then
  RESTORE_DATE="$1"
else
  if [ ! -d "$BACKUP_BASE" ]; then
    echo "❌ 备份根目录不存在：$BACKUP_BASE"
    exit 1
  fi
  RESTORE_DATE=$(ls -1 $BACKUP_BASE | sort | tail -n 1 || true)
fi

BACKUP_DIR="$BACKUP_BASE/$RESTORE_DATE"

# ------------------------------
# 检查备份目录是否存在
# ------------------------------
if [ -z "$RESTORE_DATE" ] || [ ! -d "$BACKUP_DIR" ]; then
  echo "❌ 找不到备份目录：$BACKUP_DIR"
  echo "🧾 可用的备份列表如下："
  ls -1 "$BACKUP_BASE" | sort || true
  exit 1
fi

echo "🧩 恢复日期：$RESTORE_DATE"
echo "🗂️ 备份路径：$BACKUP_DIR"

# ------------------------------
# 1️⃣ 停止 GitLab 容器
# ------------------------------
echo "🛑 停止 GitLab 容器..."
docker stop "$CONTAINER_NAME" || true

# ------------------------------
# 2️⃣ 恢复配置文件
# ------------------------------
CONFIG_ARCHIVE="$BACKUP_DIR/gitlab_config_${RESTORE_DATE}.tar.gz"
if [ -f "$CONFIG_ARCHIVE" ]; then
  echo "📁 恢复配置文件..."
  # 清空现有配置（谨慎操作）
  rm -rf "$CONFIG_DIR"/*
  mkdir -p "$CONFIG_DIR"
  tar -xzf "$CONFIG_ARCHIVE" -C "$CONFIG_DIR"
else
  echo "⚠️ 未找到配置备份文件，跳过..."
fi

# ------------------------------
# 3️⃣ 恢复日志
# ------------------------------
LOG_ARCHIVE="$BACKUP_DIR/gitlab_logs_${RESTORE_DATE}.tar.gz"
if [ -f "$LOG_ARCHIVE" ]; then
  echo "📜 恢复日志文件..."
  rm -rf "$LOG_DIR"/*
  mkdir -p "$LOG_DIR"
  tar -xzf "$LOG_ARCHIVE" -C "$LOG_DIR"
else
  echo "⚠️ 未找到日志备份文件，跳过..."
fi

# ------------------------------
# 4️⃣ 恢复数据库和仓库
# ------------------------------
echo "🗃️ 恢复 GitLab 数据..."
docker start "$CONTAINER_NAME"

# 查找备份文件（匹配 *_gitlab_backup.tar 或 *_gitlab_backup.tar.gz）
BACKUP_FILE=$(ls "$BACKUP_DIR" | grep -E "_gitlab_backup\.tar($|\.gz$)" | head -n 1 || true)

if [ -z "$BACKUP_FILE" ]; then
  echo "❌ 未找到 GitLab 数据备份文件（*_gitlab_backup.tar 或 *_gitlab_backup.tar.gz）"
  echo "🧾 备份目录内容如下："
  ls -1 "$BACKUP_DIR"
  exit 1
fi

echo "📦 复制 $BACKUP_FILE 到容器内..."
\cp -a $BACKUP_DIR/$BACKUP_FILE $DATA_DIR/backups/

# 确认容器内的文件存在
docker exec "$CONTAINER_NAME" ls -l /var/opt/gitlab/backups/
sleep 90
# 停止 GitLab 进程以保证恢复稳定（有些 Omnibus 版本通过 gitlab-ctl 管理 puma/unicorn/sidekiq）
echo "🛠️ 停止 GitLab 服务组件..."
docker exec -it "$CONTAINER_NAME" gitlab-ctl stop puma
docker exec -it "$CONTAINER_NAME" gitlab-ctl stop sidekiq
docker exec -it "$CONTAINER_NAME" gitlab-ctl stop nginx

# 提取备份编号（时间戳部分）
# 备份文件名通常像：1698200000_2025_10_25_gitlab_backup.tar
# 取第一个连续数字序列作为备份标识
TIMESTAMP=$(echo "$BACKUP_FILE" | awk -F"_gitlab" '{print $1}' | head -n 1 || true)
if [ -z "$TIMESTAMP" ]; then
  # 如果上面失败，再尝试从文件名中提取第一个下划线分隔字段
  TIMESTAMP=$(echo "$BACKUP_FILE" | awk -F'_' '{print $1}' || true)
fi

if [ -z "$TIMESTAMP" ]; then
  echo "❌ 无法识别备份文件名中的时间戳或标识: $BACKUP_FILE"
  exit 1
fi

echo "🕒 开始恢复：$TIMESTAMP"
# 如果备份是 tar.gz，gitlab-backup restore 要求的 BACKUP 参数是时间戳（目录/文件名前缀）
docker exec -it "$CONTAINER_NAME" gitlab-backup restore BACKUP="$TIMESTAMP" force=yes

# ------------------------------
# 5️⃣ 恢复完成后，重新配置并启动服务
# ------------------------------
echo "🔧 执行 reconfigure..."
docker exec -it "$CONTAINER_NAME" gitlab-ctl reconfigure

echo "🚀 启动 GitLab..."
docker exec -it "$CONTAINER_NAME" gitlab-ctl restart

echo "✅ 恢复完成！GitLab 已从 $RESTORE_DATE 的备份恢复。"
